﻿using System;
using System.Runtime.InteropServices;
using UnityEngine;

public static class DebugDraw
{
    public static void DebugArrow(Vector3 position, Vector3 direction, float duration = 0, bool depthTest = true)
    {
        DebugArrow(position, direction, Color.white, duration, depthTest);
    }

    public static void DebugArrow(Vector3 position, Vector3 direction, Color color, float duration = 0, bool depthTest = true)
    {
        Debug.DrawRay(position, direction, color, duration, depthTest);
        DebugCone(position + direction, (Vector3) (-direction * 0.333f), color, 15f, duration, depthTest);
    }

    public static void DebugBounds(Bounds bounds, float duration = 0, bool depthTest = true)
    {
        DebugBounds(bounds, Color.white, duration, depthTest);
    }

    public static void DebugBounds(Bounds bounds, Color color, float duration = 0, bool depthTest = true)
    {
        Vector3 center = bounds.center;
        float x = bounds.extents.x;
        float y = bounds.extents.y;
        float z = bounds.extents.z;
        Vector3 start = center + new Vector3(x, y, z);
        Vector3 end = center + new Vector3(x, y, -z);
        Vector3 vector4 = center + new Vector3(-x, y, z);
        Vector3 vector5 = center + new Vector3(-x, y, -z);
        Vector3 vector6 = center + new Vector3(x, -y, z);
        Vector3 vector7 = center + new Vector3(x, -y, -z);
        Vector3 vector8 = center + new Vector3(-x, -y, z);
        Vector3 vector9 = center + new Vector3(-x, -y, -z);
        Debug.DrawLine(start, vector4, color, duration, depthTest);
        Debug.DrawLine(start, end, color, duration, depthTest);
        Debug.DrawLine(vector4, vector5, color, duration, depthTest);
        Debug.DrawLine(end, vector5, color, duration, depthTest);
        Debug.DrawLine(start, vector6, color, duration, depthTest);
        Debug.DrawLine(end, vector7, color, duration, depthTest);
        Debug.DrawLine(vector4, vector8, color, duration, depthTest);
        Debug.DrawLine(vector5, vector9, color, duration, depthTest);
        Debug.DrawLine(vector6, vector8, color, duration, depthTest);
        Debug.DrawLine(vector6, vector7, color, duration, depthTest);
        Debug.DrawLine(vector8, vector9, color, duration, depthTest);
        Debug.DrawLine(vector9, vector7, color, duration, depthTest);
    }

    public static void DebugCapsule(Vector3 start, Vector3 end, float radius = 1, float duration = 0, bool depthTest = true)
    {
        DebugCapsule(start, end, Color.white, radius, duration, depthTest);
    }

    public static void DebugCapsule(Vector3 start, Vector3 end, Color color, float radius = 1, float duration = 0, bool depthTest = true)
    {
        Vector3 vector5 = end - start;
        Vector3 a = (Vector3) (vector5.normalized * radius);
        Vector3 rhs = Vector3.Slerp(a, -a, 0.5f);
        Vector3 vector3 = (Vector3) (Vector3.Cross(a, rhs).normalized * radius);
        Vector3 vector7 = start - end;
        float magnitude = vector7.magnitude;
        float num2 = Mathf.Max((float) 0f, (float) ((magnitude * 0.5f) - radius));
        Vector3 vector4 = (Vector3) ((end + start) * 0.5f);
        Vector3 vector8 = start - vector4;
        start = vector4 + ((Vector3) (vector8.normalized * num2));
        Vector3 vector9 = end - vector4;
        end = vector4 + ((Vector3) (vector9.normalized * num2));
        DebugCircle(start, a, color, radius, duration, depthTest);
        DebugCircle(end, -a, color, radius, duration, depthTest);
        Debug.DrawLine(start + vector3, end + vector3, color, duration, depthTest);
        Debug.DrawLine(start - vector3, end - vector3, color, duration, depthTest);
        Debug.DrawLine(start + rhs, end + rhs, color, duration, depthTest);
        Debug.DrawLine(start - rhs, end - rhs, color, duration, depthTest);
        for (int i = 1; i < 0x1a; i++)
        {
            Debug.DrawLine(Vector3.Slerp(vector3, -a, ((float) i) / 25f) + start, Vector3.Slerp(vector3, -a, ((float) (i - 1)) / 25f) + start, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(-vector3, -a, ((float) i) / 25f) + start, Vector3.Slerp(-vector3, -a, ((float) (i - 1)) / 25f) + start, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(rhs, -a, ((float) i) / 25f) + start, Vector3.Slerp(rhs, -a, ((float) (i - 1)) / 25f) + start, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(-rhs, -a, ((float) i) / 25f) + start, Vector3.Slerp(-rhs, -a, ((float) (i - 1)) / 25f) + start, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(vector3, a, ((float) i) / 25f) + end, Vector3.Slerp(vector3, a, ((float) (i - 1)) / 25f) + end, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(-vector3, a, ((float) i) / 25f) + end, Vector3.Slerp(-vector3, a, ((float) (i - 1)) / 25f) + end, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(rhs, a, ((float) i) / 25f) + end, Vector3.Slerp(rhs, a, ((float) (i - 1)) / 25f) + end, color, duration, depthTest);
            Debug.DrawLine(Vector3.Slerp(-rhs, a, ((float) i) / 25f) + end, Vector3.Slerp(-rhs, a, ((float) (i - 1)) / 25f) + end, color, duration, depthTest);
        }
    }

    public static void DebugCircle(Vector3 position, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        DebugCircle(position, Vector3.up, Color.white, radius, duration, depthTest);
    }

    public static void DebugCircle(Vector3 position, Color color, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        DebugCircle(position, Vector3.up, color, radius, duration, depthTest);
    }

    public static void DebugCircle(Vector3 position, Vector3 up, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        DebugCircle(position, up, Color.white, radius, duration, depthTest);
    }

    public static void DebugCircle(Vector3 position, Vector3 up, Color color, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        Vector3 a = (Vector3) (up.normalized * radius);
        Vector3 rhs = Vector3.Slerp(a, -a, 0.5f);
        Vector3 vector3 = (Vector3) (Vector3.Cross(a, rhs).normalized * radius);
        Matrix4x4 matrixx = new Matrix4x4();
        matrixx[0] = vector3.x;
        matrixx[1] = vector3.y;
        matrixx[2] = vector3.z;
        matrixx[4] = a.x;
        matrixx[5] = a.y;
        matrixx[6] = a.z;
        matrixx[8] = rhs.x;
        matrixx[9] = rhs.y;
        matrixx[10] = rhs.z;
        Vector3 start = position + matrixx.MultiplyPoint3x4(new Vector3(Mathf.Cos(0f), 0f, Mathf.Sin(0f)));
        Vector3 zero = Vector3.zero;
        color = !(color == new Color()) ? color : Color.white;
        for (int i = 0; i < 0x5b; i++)
        {
            zero.x = Mathf.Cos((i * 4) * 0.01745329f);
            zero.z = Mathf.Sin((i * 4) * 0.01745329f);
            zero.y = 0f;
            zero = position + matrixx.MultiplyPoint3x4(zero);
            Debug.DrawLine(start, zero, color, duration, depthTest);
            start = zero;
        }
    }

    public static void DebugCone(Vector3 position, float angle = 0x2d, float duration = 0, bool depthTest = true)
    {
        DebugCone(position, Vector3.up, Color.white, angle, duration, depthTest);
    }

    public static void DebugCone(Vector3 position, Color color, float angle = 0x2d, float duration = 0, bool depthTest = true)
    {
        DebugCone(position, Vector3.up, color, angle, duration, depthTest);
    }

    public static void DebugCone(Vector3 position, Vector3 direction, float angle = 0x2d, float duration = 0, bool depthTest = true)
    {
        DebugCone(position, direction, Color.white, angle, duration, depthTest);
    }

    public static void DebugCone(Vector3 position, Vector3 direction, Color color, float angle = 0x2d, float duration = 0, bool depthTest = true)
    {
        float num2;
        float magnitude = direction.magnitude;
        Vector3 a = direction;
        Vector3 rhs = Vector3.Slerp(a, -a, 0.5f);
        Vector3 b = (Vector3) (Vector3.Cross(a, rhs).normalized * magnitude);
        direction = direction.normalized;
        Vector3 vector4 = Vector3.Slerp(a, rhs, angle / 90f);
        Plane plane = new Plane(-direction, position + a);
        Ray ray = new Ray(position, vector4);
        plane.Raycast(ray, out num2);
        Debug.DrawRay(position, (Vector3) (vector4.normalized * num2), color);
        Debug.DrawRay(position, (Vector3) (Vector3.Slerp(a, -rhs, angle / 90f).normalized * num2), color, duration, depthTest);
        Debug.DrawRay(position, (Vector3) (Vector3.Slerp(a, b, angle / 90f).normalized * num2), color, duration, depthTest);
        Debug.DrawRay(position, (Vector3) (Vector3.Slerp(a, -b, angle / 90f).normalized * num2), color, duration, depthTest);
        Vector3 vector9 = a - ((Vector3) (vector4.normalized * num2));
        DebugCircle(position + a, direction, color, vector9.magnitude, duration, depthTest);
        Vector3 vector10 = (Vector3) ((a * 0.5f) - (vector4.normalized * (num2 * 0.5f)));
        DebugCircle(position + ((Vector3) (a * 0.5f)), direction, color, vector10.magnitude, duration, depthTest);
    }

    public static void DebugCylinder(Vector3 start, Vector3 end, float radius = 1, float duration = 0, bool depthTest = true)
    {
        DebugCylinder(start, end, Color.white, radius, duration, depthTest);
    }

    public static void DebugCylinder(Vector3 start, Vector3 end, Color color, float radius = 1, float duration = 0, bool depthTest = true)
    {
        Vector3 vector4 = end - start;
        Vector3 a = (Vector3) (vector4.normalized * radius);
        Vector3 rhs = Vector3.Slerp(a, -a, 0.5f);
        Vector3 vector3 = (Vector3) (Vector3.Cross(a, rhs).normalized * radius);
        DebugCircle(start, a, color, radius, duration, depthTest);
        DebugCircle(end, -a, color, radius, duration, depthTest);
        DebugCircle((Vector3) ((start + end) * 0.5f), a, color, radius, duration, depthTest);
        Debug.DrawLine(start + vector3, end + vector3, color, duration, depthTest);
        Debug.DrawLine(start - vector3, end - vector3, color, duration, depthTest);
        Debug.DrawLine(start + rhs, end + rhs, color, duration, depthTest);
        Debug.DrawLine(start - rhs, end - rhs, color, duration, depthTest);
        Debug.DrawLine(start - vector3, start + vector3, color, duration, depthTest);
        Debug.DrawLine(start - rhs, start + rhs, color, duration, depthTest);
        Debug.DrawLine(end - vector3, end + vector3, color, duration, depthTest);
        Debug.DrawLine(end - rhs, end + rhs, color, duration, depthTest);
    }

    public static void DebugLocalCube(Matrix4x4 space, Vector3 size, [Optional] Vector3 center, float duration = 0, bool depthTest = true)
    {
        DebugLocalCube(space, size, Color.white, center, duration, depthTest);
    }

    public static void DebugLocalCube(Transform transform, Vector3 size, [Optional] Vector3 center, float duration = 0, bool depthTest = true)
    {
        DebugLocalCube(transform, size, Color.white, center, duration, depthTest);
    }

    public static void DebugLocalCube(Matrix4x4 space, Vector3 size, Color color, [Optional] Vector3 center, float duration = 0, bool depthTest = true)
    {
        color = !(color == new Color()) ? color : Color.white;
        Vector3 start = space.MultiplyPoint3x4(center + ((Vector3) (-size * 0.5f)));
        Vector3 end = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(size.x, -size.y, -size.z) * 0.5f)));
        Vector3 vector3 = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(size.x, -size.y, size.z) * 0.5f)));
        Vector3 vector4 = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(-size.x, -size.y, size.z) * 0.5f)));
        Vector3 vector5 = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(-size.x, size.y, -size.z) * 0.5f)));
        Vector3 vector6 = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(size.x, size.y, -size.z) * 0.5f)));
        Vector3 vector7 = space.MultiplyPoint3x4(center + ((Vector3) (size * 0.5f)));
        Vector3 vector8 = space.MultiplyPoint3x4(center + ((Vector3) (new Vector3(-size.x, size.y, size.z) * 0.5f)));
        Debug.DrawLine(start, end, color, duration, depthTest);
        Debug.DrawLine(end, vector3, color, duration, depthTest);
        Debug.DrawLine(vector3, vector4, color, duration, depthTest);
        Debug.DrawLine(vector4, start, color, duration, depthTest);
        Debug.DrawLine(vector5, vector6, color, duration, depthTest);
        Debug.DrawLine(vector6, vector7, color, duration, depthTest);
        Debug.DrawLine(vector7, vector8, color, duration, depthTest);
        Debug.DrawLine(vector8, vector5, color, duration, depthTest);
        Debug.DrawLine(start, vector5, color, duration, depthTest);
        Debug.DrawLine(end, vector6, color, duration, depthTest);
        Debug.DrawLine(vector3, vector7, color, duration, depthTest);
        Debug.DrawLine(vector4, vector8, color, duration, depthTest);
    }

    public static void DebugLocalCube(Transform transform, Vector3 size, Color color, [Optional] Vector3 center, float duration = 0, bool depthTest = true)
    {
        Vector3 start = transform.TransformPoint(center + ((Vector3) (-size * 0.5f)));
        Vector3 end = transform.TransformPoint(center + ((Vector3) (new Vector3(size.x, -size.y, -size.z) * 0.5f)));
        Vector3 vector3 = transform.TransformPoint(center + ((Vector3) (new Vector3(size.x, -size.y, size.z) * 0.5f)));
        Vector3 vector4 = transform.TransformPoint(center + ((Vector3) (new Vector3(-size.x, -size.y, size.z) * 0.5f)));
        Vector3 vector5 = transform.TransformPoint(center + ((Vector3) (new Vector3(-size.x, size.y, -size.z) * 0.5f)));
        Vector3 vector6 = transform.TransformPoint(center + ((Vector3) (new Vector3(size.x, size.y, -size.z) * 0.5f)));
        Vector3 vector7 = transform.TransformPoint(center + ((Vector3) (size * 0.5f)));
        Vector3 vector8 = transform.TransformPoint(center + ((Vector3) (new Vector3(-size.x, size.y, size.z) * 0.5f)));
        Debug.DrawLine(start, end, color, duration, depthTest);
        Debug.DrawLine(end, vector3, color, duration, depthTest);
        Debug.DrawLine(vector3, vector4, color, duration, depthTest);
        Debug.DrawLine(vector4, start, color, duration, depthTest);
        Debug.DrawLine(vector5, vector6, color, duration, depthTest);
        Debug.DrawLine(vector6, vector7, color, duration, depthTest);
        Debug.DrawLine(vector7, vector8, color, duration, depthTest);
        Debug.DrawLine(vector8, vector5, color, duration, depthTest);
        Debug.DrawLine(start, vector5, color, duration, depthTest);
        Debug.DrawLine(end, vector6, color, duration, depthTest);
        Debug.DrawLine(vector3, vector7, color, duration, depthTest);
        Debug.DrawLine(vector4, vector8, color, duration, depthTest);
    }

    public static void DebugPoint(Vector3 position, float scale = 1f, float duration = 0, bool depthTest = true)
    {
        DebugPoint(position, Color.white, scale, duration, depthTest);
    }

    public static void DebugPoint(Vector3 position, Color color, float scale = 1f, float duration = 0, bool depthTest = true)
    {
        color = !(color == new Color()) ? color : Color.white;
        Debug.DrawRay(position + ((Vector3) (Vector3.up * (scale * 0.5f))), (Vector3) (-Vector3.up * scale), color, duration, depthTest);
        Debug.DrawRay(position + ((Vector3) (Vector3.right * (scale * 0.5f))), (Vector3) (-Vector3.right * scale), color, duration, depthTest);
        Debug.DrawRay(position + ((Vector3) (Vector3.forward * (scale * 0.5f))), (Vector3) (-Vector3.forward * scale), color, duration, depthTest);
    }

    public static void DebugWireSphere(Vector3 position, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        DebugWireSphere(position, Color.white, radius, duration, depthTest);
    }

    public static void DebugWireSphere(Vector3 position, Color color, float radius = 1f, float duration = 0, bool depthTest = true)
    {
        float num = 10f;
        Vector3 start = new Vector3(position.x, position.y + (radius * Mathf.Sin(0f)), position.z + (radius * Mathf.Cos(0f)));
        Vector3 vector2 = new Vector3(position.x + (radius * Mathf.Cos(0f)), position.y, position.z + (radius * Mathf.Sin(0f)));
        Vector3 vector3 = new Vector3(position.x + (radius * Mathf.Cos(0f)), position.y + (radius * Mathf.Sin(0f)), position.z);
        for (int i = 1; i < 0x25; i++)
        {
            Vector3 end = new Vector3(position.x, position.y + (radius * Mathf.Sin((num * i) * 0.01745329f)), position.z + (radius * Mathf.Cos((num * i) * 0.01745329f)));
            Vector3 vector5 = new Vector3(position.x + (radius * Mathf.Cos((num * i) * 0.01745329f)), position.y, position.z + (radius * Mathf.Sin((num * i) * 0.01745329f)));
            Vector3 vector6 = new Vector3(position.x + (radius * Mathf.Cos((num * i) * 0.01745329f)), position.y + (radius * Mathf.Sin((num * i) * 0.01745329f)), position.z);
            Debug.DrawLine(start, end, color, duration, depthTest);
            Debug.DrawLine(vector2, vector5, color, duration, depthTest);
            Debug.DrawLine(vector3, vector6, color, duration, depthTest);
            start = end;
            vector2 = vector5;
            vector3 = vector6;
        }
    }

    public static void DrawArrow(Vector3 pos, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20f)
    {
        Debug.DrawRay(pos, direction);
        DrawArrowEnd(pos, direction, Gizmos.color, arrowHeadLength, arrowHeadAngle);
    }

    public static void DrawArrow(Vector3 pos, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20f)
    {
        Debug.DrawRay(pos, direction, color);
        DrawArrowEnd(pos, direction, color, arrowHeadLength, arrowHeadAngle);
    }

    private static void DrawArrowEnd(Vector3 pos, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20f)
    {
        if (direction != Vector3.zero)
        {
            Vector3 vector = (Vector3) ((Quaternion.LookRotation(direction) * Quaternion.Euler(arrowHeadAngle, 0f, 0f)) * Vector3.back);
            Vector3 vector2 = (Vector3) ((Quaternion.LookRotation(direction) * Quaternion.Euler(-arrowHeadAngle, 0f, 0f)) * Vector3.back);
            Vector3 vector3 = (Vector3) ((Quaternion.LookRotation(direction) * Quaternion.Euler(0f, arrowHeadAngle, 0f)) * Vector3.back);
            Vector3 vector4 = (Vector3) ((Quaternion.LookRotation(direction) * Quaternion.Euler(0f, -arrowHeadAngle, 0f)) * Vector3.back);
            Debug.DrawRay(pos + direction, (Vector3) (vector * arrowHeadLength), color);
            Debug.DrawRay(pos + direction, (Vector3) (vector2 * arrowHeadLength), color);
            Debug.DrawRay(pos + direction, (Vector3) (vector3 * arrowHeadLength), color);
            Debug.DrawRay(pos + direction, (Vector3) (vector4 * arrowHeadLength), color);
        }
    }

    private static void DrawLine(Vector3 start, Vector3 end, Color color, float duration)
    {
        if (Application.isPlaying)
        {
            Debug.DrawLine(start, end, color, duration);
        }
    }

    public static void DrawPoly(Transform tsm, Vector2[] points)
    {
        DrawPoly(tsm, points, Color.white, 0.01f);
    }

    public static unsafe void DrawPoly(Transform tsm, Vector2[] points, Color color, float duration = 0.01f)
    {
        for (int i = 0; i < (points.Length - 1); i++)
        {
            Debug.DrawLine(tsm.TransformPoint(*((Vector3*) &(points[i]))), tsm.TransformPoint(*((Vector3*) &(points[i + 1]))), color, duration);
        }
        DrawLine(tsm.TransformPoint(*((Vector3*) &(points[points.Length - 1]))), tsm.TransformPoint(*((Vector3*) &(points[0]))), color, duration);
    }

    public static void DrawRect(Rect rect)
    {
        DrawRect(rect, Color.white, 0.01f);
    }

    public static void DrawRect(Rect rect, Color color, float duration = 0.01f)
    {
        DrawLine((Vector3) rect.min, (Vector3) new Vector2(rect.xMin, rect.yMax), color, duration);
        DrawLine((Vector3) new Vector2(rect.xMin, rect.yMax), (Vector3) rect.max, color, duration);
        DrawLine((Vector3) rect.max, (Vector3) new Vector2(rect.xMax, rect.yMin), color, duration);
        DrawLine((Vector3) new Vector2(rect.xMax, rect.yMin), (Vector3) rect.min, color, duration);
    }
}

